/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c) 2002, GeoVISTA Center
 * Licensed under Simplified BSD License
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * @original author: jin Chen 
 * @author: jin Chen 
 * @date: Nov 10, 2008$
 * @version: 1.0
 */
package edu.psu.geovista.app.vit.pub.action;

import edu.psu.geovista.app.coordinator.CoordinationManager;
import edu.psu.geovista.app.gmap.SimpleGeoMap;
import edu.psu.geovista.app.visualclassifier.classify.v2.ESVisualClassifier;
import edu.psu.geovista.app.visualclassifier.classify.v2.agent.ClassifyAgent;
import edu.psu.geovista.app.vit.pub.VitPub;
import edu.psu.geovista.app.vit.pub.components.ptnbskt.MyBasket;
import edu.psu.geovista.app.vit.pub.components.sts.SSReader;
import edu.psu.geovista.app.vit.pub.components.sts.SSResult;
import edu.psu.geovista.app.vit.pub.utils.VitUtils;
import edu.psu.geovista.app.vit.pub.views.View;
import edu.psu.geovista.app.vit.pub.views.VitPubViewMgr;
import edu.psu.geovista.classification.setting.ClassifySetting;
import edu.psu.geovista.classification.setting.ClassifySetting1D;
import edu.psu.geovista.common.utils.collection.CollectionUtils;
import edu.psu.geovista.data.model.AppDataModel;
import edu.psu.geovista.data.model.DefaultAppDataModel;
import edu.psu.geovista.ui.event.ClassificationResultListener;
import edu.psu.geovista.ui.event.ColorArrayListener;
import epoviz.trex.common.swing.components.internalframe.SimpleInternalFrame;

import javax.swing.*;
import java.awt.*;
import java.util.*;

public class VitPubActionManager {
    VitPub vit;
    SSReader satscanReader;
    ConfigRMapPane askp;
     SimpleInternalFrame frame;
       MyBasket basket;
    public VitPubActionManager(VitPub vit) {
        this.vit = vit;
         basket = new MyBasket(vit);
        CoordinationManager coordmanager = vit.getCoordMgr();
       coordmanager.addBean(basket); 
    }
    public void showPatternBasket(){
        if(frame==null){
            VitPub vit = this.getVitApp();
            Map<Object,Integer> id2indexs = vit.getId2Index();
            JDesktopPane desktop = vit.getDesktop();


            basket.setId2Index(id2indexs);
           /* Map<Object,Integer> id2index = vit.getId2Index();
            basket.setId2Index(id2index) ;*/
            frame = SimpleInternalFrame.addComponent(desktop, basket, MyBasket.TITLE, new Dimension(400,400));
            frame.setVisible(false);//will be set visible later
        }
         SimpleInternalFrame frm = frame;
           if(frm.isVisible()||frm.isMaximum()) {
               frm.setVisible(false);
           }
           else{
               frm.setVisible(true);
               frm.setMaximizable(true);
           }

    }
    public void importSts(){
        if(satscanReader==null){
            satscanReader=new SSReader();
            Map<Object,Integer> id2indx = vit.getId2Index();
            satscanReader.setID2Index(id2indx);
            CoordinationManager coordMgr = vit.getCoordMgr();//vit.getViewMgr().get
           coordMgr.addBean(satscanReader);
        }
        satscanReader.loadSatScanData();
    }
    

    public void addRMap(){
        if(satscanReader==null||satscanReader.getResults().size() <=0){
            JOptionPane.showMessageDialog(vit,"Please load SaTScan clusters first.");
            return;
        }

       Map<Object, SSResult> satscanResults = satscanReader.getResults();
         Set<Object> sessionIdset = satscanResults.keySet();
         Object[] satscanResultIds = CollectionUtils.convert2Array(sessionIdset);
         SSResult.PerentageComparator comp=new SSResult.PerentageComparator();
         Arrays.sort(satscanResultIds,comp);
         if(askp==null) askp=new ConfigRMapPane();
         askp.setSaTScanSessionIds(satscanResultIds);
         askp.deselAll();
         Object[] buttns=new Object[]{"Ok","Cancel"};
         int i = VitUtils.showDialog(vit, askp, "Generate cluster reliability data", buttns);
        if(i==JOptionPane.OK_OPTION){
             //ImportSatScanAction impt = (ImportSatScanAction) vit.getActionMgr().getAction(ImportSatScanAction.class);
             //SatScanReader reader = impt.getSatscanReader();
             double pvalue = 0.05;

            AppDataModel srcdata = vit.getDataModel();
            String dataname = srcdata.getDataName();
            if(srcdata.getRowCount()==0){
                 JOptionPane.showMessageDialog(vit,"The source data is empty, unable to process.");
                 return;
             }
             ///Object[] ids = srcdata.getColumnIds();
             String[] rownames = srcdata.getRownames();
             String ID = "FIPS";
            Object[] fips = srcdata.getNonNumericColumnData("FIPS");
            Vector idCol = VitUtils.convert2Vector(fips);
            Vector reliableColumn =new Vector(idCol.size());// 
             if(satscanReader==null){
                 JOptionPane.showMessageDialog(vit,"You need to load SaTScan result first. Click on Tools > Import SaTScan results");
                 return;
             }
             Set selectedSessionIds = askp.getSelectedSessionIds();// the session user choose for calculate reliability
             int sessioncount = selectedSessionIds.size();
             if(sessioncount>=9){
                JOptionPane.showMessageDialog(vit,"Please select less than 9 results.");
                 return;
             }
             Map<Object,Double> dataid2rel = satscanReader.getReliableValue(pvalue,selectedSessionIds);  // 
             Set<Double> uniqueReliabValues=new HashSet<Double>(); // 
             uniqueReliabValues.add(0.0);
             for (Iterator iterator = idCol.iterator(); iterator.hasNext();) {
                 Object id = (Object) iterator.next();
                 Double reliablev = dataid2rel.get(id);
                 if(reliablev!=null) {
                     Float relv=new Float(reliablev);
                     reliableColumn.add(relv);
                    uniqueReliabValues.add(reliablev);
                 }
                 else
                    reliableColumn.add(0.0f); // 
             }

            // srcdata.addColumn(ColumnName_RELIABILITY_VALUES, reliableColumn);
            // 
             AppDataModel reliabilityModel=new DefaultAppDataModel();
             reliabilityModel.setRowNames(idCol);// 
             reliabilityModel.addColumn("Reliability Values", reliableColumn);
             //add shp data to show map
             AppDataModel dfdata = vit.getDataModel();
             Shape[] shpvalues = dfdata.getShpData();
             reliabilityModel.setShpData(shpvalues);
            /* //DataLoader dataloader = vit.getDataloader();
             AppDataModel relibdata= null;
             try {
                 relibdata = vit.getData(DataName_RELIABILITY);
                 if(relibdata==null)   {
                      //create reliability model and the corresponding data variable
                         dataloader.addDataRuntime(DataName_RELIABILITY,reliabilityModel, false);  // 
                          vit.createDefaultDataVaraible(DataName_RELIABILITY);
                 }else{
                     relibdata.setColumn(ColumnName_RELIABILITY_VALUES, reliableColumn);
                 }
             } catch (Exception e) {
                 JOptionPane.showMessageDialog(vit,e.toString());
                 e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
             }
             //classfication values for the reliability map*/
             double[] unqRelibs = VitUtils.convert2DoubleArray(uniqueReliabValues);
             double[] classifyvalues = classify(unqRelibs);
             //String values = classifyvalues.toString();
             if(unqRelibs.length >0){// reliablity values exist
                 VitPubViewMgr viewMgr = vit.getViewMgr();
                 View rmview = viewMgr.getView("Reliability Map");

                 if(rmview==null){
                     //create map view
                     rmview=viewMgr.createView("Reliability Map",View.TYPE_GEOMAP);
                     rmview.setSave(false);// 
                 }
                SimpleGeoMap map = (SimpleGeoMap) rmview.getViewComponent();
                 //the map may not have data - u load the project after the 1st time, the reliability data is not available, although the map is instantiated
                 // SimpleGeoMap map = new SimpleGeoMap();
                /* AppDataModel mapmodel = map.getDataModel();
                 if(mapmodel==null||mapmodel.getShpData()==null){//
                     try {
                         map.setDataModel(reliabilityModel);
                          mapmodel = map.getDataModel();
                     } catch (Exception e) {
                         e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                     }
                 }*/
                 
                 try {
                     map.setDataModel(reliabilityModel);
                 } catch (Exception e) {
                     e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                 }
                 // 
                 map.setVisualClassifier(null);// 
                 ClassifyAgent clsr = map.getClassifyAgent();
                 ESVisualClassifier vc = clsr.getVisualClassifier();
                 vc.addClassificationResultListener((ClassificationResultListener) map);
                 vc.addColorArrayListener((ColorArrayListener) map);
                 map.setVisualClassifier(vc);
                 vc.setDataModel(reliabilityModel);
                 final ClassifySetting1D sett=new ClassifySetting1D();
                 sett.setVariableName("Reliability Values");
                 sett.setBoundaries(classifyvalues);
                 sett.setClassifier(ClassifySetting.SELF_DEFINED);


                 vc.classify(sett);
                 vc.broadcast();

             }
             else{
                 JOptionPane.showMessageDialog(vit,"No reliability value is found, unable to create reliablity map.");

             }


         }

    }
     /**
     * make the classification boundary for the reliability values
     * @param unqRelibs
     * @return
     */
    private double[] classify(double[] unqRelibs) {
        Arrays.sort(unqRelibs);
        double[] classifyvalues=new double[unqRelibs.length +1];
        for (int j=1;j<unqRelibs.length;j++){//the first value =0
           classifyvalues[j]= unqRelibs[j];
        }
        // 
        classifyvalues[classifyvalues.length-2]=1.0-0.001;
        classifyvalues[classifyvalues.length -1]=1.0;//reliability value of 1.0
        return classifyvalues;
    }
    private VitPub getVitApp() {
        return vit;
    }

    public MyBasket getBasket() {
        return basket;
    }
}
